#ifndef _LV_DRAW_GIF_PLAYER_H_
#define _LV_DRAW_GIF_PLAYER_H_

#ifdef __cplusplus
extern "C" {
#endif
#include "lv_conf.h"

#ifdef USE_LV_DRAW_GIF_PLAYER

#include "lvgl/src/lv_misc/lv_color.h"
#include "lvgl/src/lv_misc/lv_task.h"
#include "lvgl/src/lv_draw/lv_draw_img.h"
#include "lvgl/src/lv_core/lv_disp.h"

#define GIF_MAX_COLOR_COUNT         256

// below defines could be configured
#define GIF_USE_FILE_SYSTEM     0
#define GIF_MAX_FRAMS_COUNT     128

enum {
    COLOR_FORMAT_RGB565,
    COLOR_FORMAT_RGB565_ALPHA,
};

typedef void (*gif_ready_callback)(void *param);

//Logical Screen Descriptor
typedef struct {
    uint16_t width;
    uint16_t height;
    uint8_t pal_bits: 3;
    uint8_t sort_flag: 1;
    uint8_t color_res: 3;
    uint8_t global_pal_flag: 1;
    uint8_t background;
    uint8_t aspect;
}__attribute__((packed))gif_lsd_info_t;

typedef struct {
    uint16_t left;
    uint16_t top;
    uint16_t width;
    uint16_t height;
    uint8_t pal_bits: 3;
    uint8_t reserved: 2;
    uint8_t sort_flag: 1;
    uint8_t interlace: 1;
    uint8_t local_pal_flag: 1;
}__attribute__((packed))gif_image_info_t;

typedef struct {
    uint8_t trans_enable: 1;
    uint8_t input_enable: 1;
    uint8_t disposal_method: 3;
    uint8_t reserved: 3;
    uint16_t delay_time;       //// unit: 1/100 second
    uint8_t trans_color_index;
}__attribute__((packed))gif_graphic_ctrl_ext_t;

typedef struct {
    gif_image_info_t image_info;
    gif_graphic_ctrl_ext_t graphic_ctrl;
    lv_color_rgb888_t *local_color_table;
    uint32_t file_offset;
    uint32_t frame_size;
} gif_frame_info_t;

struct lzw_info_t {
    uint8_t *out_ptr;
    int cnt_size;
    int bit_size;
    int old_code;
    int idx_max;
    int cnt_clear;
    int mask;
    uint8_t **dict_p;
    int *dict_length;
    uint8_t color[256];
};

typedef struct {
    uint8_t not_free_flag;   /* 0xbe: use,  other: free */
    void *file_p;
    gif_lsd_info_t lsd_info;
    lv_color_rgb888_t global_color_table[GIF_MAX_COLOR_COUNT];
    uint32_t frames_count;
    uint32_t current_frame_index;
    gif_frame_info_t *frames[GIF_MAX_FRAMS_COUNT];
    uint8_t *render_bmp;
    bool hasdm2;  //true: if has a frame with disposal_method 2
    uint8_t *render_bmp_a; //to keep alpha when hasdm2 is true
    void *animation_timer;
    uint8_t render_color_format;
    void *gif_img_obj;
    gif_ready_callback ready_callback;
    struct lzw_info_t *lzw_info;

    lv_img_dsc_t gif_frame;
    lv_obj_t *img1;
    lv_task_t *gif_anim_task;
    int once;
    int once_done;
    int x;
    int y;
    lv_color_rgba8888_t *canvas;
    lv_obj_t *container;
    lv_obj_t *par;
} gif_info_t;

void *gif_open(lv_obj_t *par, const void* src, int once);
int gif_close(gif_info_t *info);

#endif /* USE_LV_DRAW_GIF_PLAYER */

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif
